package com.chunyu.app.utils;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import java.util.zip.CRC32;
import java.util.zip.Checksum;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FileUtils {
	public static Logger logger = LoggerFactory.getLogger(FileUtils.class);
	protected static final Pattern ILLEGAL_CURRENT_FOLDER_PATTERN = Pattern.compile("^[^/]|[^/]$|/\\.{1,2}|\\\\|\\||:|\\?|\\*|\"|<|>|\\p{Cntrl}");

	public static void copyFile(final File srcFile, final File destFile) {
		try {
			org.apache.commons.io.FileUtils.copyFile(srcFile, destFile);
		} catch (IOException e) {
			logger.error("copyFile", e);
		}
	}

	/**
	 * 关闭相关资源
	 * 
	 * @param closeable
	 */
	public static void closeQuietly(final Closeable closeable) {
		if (closeable == null) {
			return;
		}
		try {
			closeable.close();
		} catch (Exception exc) {

		}
	}

	public static long calculateChecksum(byte[] data) {
		Checksum sum = new CRC32();
		sum.update(data, 0, data.length);
		return sum.getValue();
	}

	public static long calculateChecksum(InputStream stream) throws IOException {
		Checksum sum = new CRC32();

		byte[] buf = new byte[4096];
		int count;
		while ((count = stream.read(buf)) != -1) {
			if (count > 0) {
				sum.update(buf, 0, count);
			}
		}
		return sum.getValue();
	}

	public static String sanitizeFileName(final String filename) {

		if (StringUtils.isBlank(filename)) {
			return filename;
		}
		String name = forceSingleExtension(filename);
		// Remove \ / | : ? * " < > 'Control Chars' with _
		return name.replaceAll("\\\\|/|\\||:|\\?|\\*|\"|<|>|\\p{Cntrl}", "_");
	}

	public static String sanitizeFolderName(final String folderName) {
		if (StringUtils.isBlank(folderName)) {
			return folderName;
		}
		// Remove . \ / | : ? * " < > 'Control Chars' with _
		return folderName.replaceAll("\\.|\\\\|/|\\||:|\\?|\\*|\"|<|>|\\p{Cntrl}", "_");
	}

	public static boolean isValidPath(final String path) {
		if (StringUtils.isBlank(path)) {
			return false;
		} else if (ILLEGAL_CURRENT_FOLDER_PATTERN.matcher(path).find()) {
			return false;
		}
		return true;
	}

	public static String forceSingleExtension(final String filename) {
		return filename.replaceAll("\\.(?![^.]+$)", "_");
	}

	public static boolean isSingleExtension(final String filename) {
		return filename.matches("[^\\.]+\\.[^\\.]+");
	}

	public static String getSimpleFileFormat() {
		return "{yyyy}{mm}{dd}/{time}{rand:6}";
	}

	/**
	 * 生成当前年月格式的文件路径
	 * 
	 * yyyyMM 200806
	 * 
	 * @return
	 */
	public static String genPathName() {
		return DateUtils.currentDate2YyyyMMStr();
	}

	public static String genFileName(String path, String fileName, String ext) {
		return path + fileName + "." + ext;
	}

	public static String getExtension(String fileName) {
		return FilenameUtils.getExtension(fileName).toLowerCase();
	}

	public static String getExtensionWithDot(String fileName) {
		return "." + getExtension(fileName);
	}

	public static String trimExtension(String filename) {
		if ((filename != null) && (filename.length() > 0)) {
			int dot = filename.lastIndexOf('.');
			if ((dot > -1) && (dot < (filename.length()))) {
				return filename.substring(0, dot);
			}
		}
		return filename;
	}

	/**
	 * 文件大小格式转换，转换成KB，MB，GB
	 * 
	 * @param size
	 * @return
	 */
	public static String convertFileSize(long size) {
		long kb = 1024;
		long mb = kb * 1024;
		long gb = mb * 1024;

		if (size >= gb) {
			return String.format("%.1f GB", (float) size / gb);
		} else if (size >= mb) {
			float f = (float) size / mb;
			return String.format(f > 100 ? "%.0f MB" : "%.1f MB", f);
		} else if (size >= kb) {
			float f = (float) size / kb;
			return String.format(f > 100 ? "%.0f KB" : "%.1f KB", f);
		} else
			return String.format("%d B", size);
	}

	public static List<File> getFiles(File folder) {
		List<File> files = new ArrayList<File>();
		iterateFolder(folder, files);
		return files;
	}

	private static void iterateFolder(File folder, List<File> files) {
		File flist[] = folder.listFiles();
		files.add(folder);
		if (flist == null || flist.length == 0) {
			files.add(folder);
		} else {
			for (File f : flist) {
				if (f.isDirectory()) {
					iterateFolder(f, files);
				} else {
					files.add(f);
				}
			}
		}
	}

	public static String filter(String input) {

		return input.replaceAll("/\\*[\\s\\S]*?\\*/", "");
	}

	public static final String parseFileName(String fileName) {
		String filePath = formatPath(fileName);
		String[] filePathList = filePath.split("/");
		if (filePathList.length > 0) {
			String[] fileNameList = filePathList[filePathList.length - 1].split(".");
			if (fileNameList.length > 0) {
				return fileNameList[0];
			} else {
				return fileName;
			}
		} else {
			String[] fileNameList = fileName.split(".");
			if (fileNameList.length > 0) {
				return fileNameList[0];
			} else {
				return fileName;
			}
		}
	}

	public static String readFileString(String path) {
		return readFileString(path, "UTF-8");
	}

	/**
	 * 读取文件字符串
	 * 
	 * @param path
	 * @return
	 * @throws IOException
	 */
	public static String readFileString(String path, String charset) {
		StringBuilder builder = new StringBuilder();
		InputStreamReader reader = null;
		BufferedReader bfReader = null;
		FileInputStream fin = null;
		try {
			fin = new FileInputStream(path);
			reader = new InputStreamReader(fin, charset);
			bfReader = new BufferedReader(reader);
			String tmpContent = null;
			while ((tmpContent = bfReader.readLine()) != null) {
				builder.append(tmpContent);
			}
			bfReader.close();

		} catch (Exception e) {
			logger.error("read[" + path + "] error", e);
		} finally {
			FileUtils.closeQuietly(reader);
			FileUtils.closeQuietly(bfReader);
			FileUtils.closeQuietly(fin);
		}
		return filter(builder.toString());
	}

	/**
	 * 读取文件字符串
	 * 
	 * @param path
	 * @return
	 * @throws IOException
	 */
	public static String readFileString(File path) {
		StringBuilder builder = new StringBuilder();
		try {
			InputStreamReader reader = new InputStreamReader(new FileInputStream(path), "UTF-8");
			BufferedReader bfReader = new BufferedReader(reader);
			String tmpContent = null;
			while ((tmpContent = bfReader.readLine()) != null) {
				builder.append(tmpContent);
			}
			bfReader.close();

		} catch (Exception e) {
			logger.error("read[" + path + "] error", e);
		}

		return filter(builder.toString());

	}

	/**
	 * 格式化路径, 把windows路径替换成标准路径
	 * 
	 * @param input
	 *            待格式化的路径
	 * @return 格式化后的路径
	 */
	public static String formatPath(String input) {

		return input.replace("\\", "/").replaceAll("//", "/");

	}

	public static void createDirs(String path) {
		File destFile = new File(path);
		if (!destFile.exists()) {
			destFile.mkdirs();
		}
	}

	public static void delete(String path) {
		File destFile = new File(path);
		if (destFile.exists()) {
			destFile.delete();
		}
	}

	/**
	 * 解析文件后缀名
	 * 
	 * @return
	 */
	public static final String parseFileSuffix(String fileName) {
		if (NullUtils.isEmpty(fileName)) {
			return "";
		} else {
			String[] tempArray = fileName.split("[.]");
			if (tempArray.length > 1) {
				return tempArray[tempArray.length - 1];
			} else {
				return "";
			}
		}
	}

	public static byte[] readBytes(String fileName) {
		return readBytes(new File(formatPath(fileName)));
	}

	public static byte[] readBytes(File file) {
		FileInputStream is = null;
		try {
			is = new FileInputStream(file);
			return readBytes(is);
		} catch (Exception e) {
			logger.error("readBytes", e);
			return null;
		} finally {
			closeQuietly(is);
		}
	}

	public static byte[] readBytes(InputStream in) {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		try {
			IOUtils.copy(in, baos);
			if (baos.size() > 0) {
				return baos.toByteArray();
			} else {
				return null;
			}
		} catch (Exception e) {
			logger.error("readBytes", e);
			return null;
		} finally {
			closeQuietly(baos);
		}
	}

	public static void copyFile(String oldfile, String newFile) throws Exception {
		copyFile(new File(oldfile), new File(newFile));
	}

	public static void moveFile(String oldfile, String newFile) throws Exception {
		copyFile(new File(oldfile), new File(newFile));
	}

	public static void moveFile(File oldfile, File newFile) throws Exception {
		FileInputStream fin = null;
		FileOutputStream fout = null;
		try {
			if (oldfile.exists()) { // 文件存在时
				fin = new FileInputStream(oldfile); // 读入原文件
				fout = new FileOutputStream(newFile);
				IOUtils.copy(fin, fout);
				delete(oldfile);
			}
		} finally {
			FileUtils.closeQuietly(fin);
			FileUtils.closeQuietly(fout);
		}
	}

	public static void write(InputStream is, FileOutputStream out) {
		write(is, out);
	}

	public static void write(byte[] data, String fileName) throws Exception {
		File file = new File(formatPath(fileName));
		createDirs(file.getParentFile());
		write(data, file);
	}

	public static void write(String content, OutputStream out) throws Exception {
		try {
			write(content.getBytes("UTF-8"), out);
		} catch (Exception e) {
			logger.error("write", e);
			throw e;
		}
	}

	public static void write(String content, String fileName) throws Exception {
		File file = new File(fileName);
		createDirs(file.getParentFile());
		try {
			write(content.getBytes("UTF-8"), file);
		} catch (Exception e) {
			logger.error("write", e);
			throw e;
		}
	}

	public static void write(String content, File file) throws Exception {
		createDirs(file.getParentFile());
		try {
			write(content.getBytes("UTF-8"), file);
		} catch (Exception e) {
			logger.error("write", e);
			throw e;
		}
	}

	public static void write(byte[] data, File file) throws Exception {
		FileOutputStream out = null;
		try {
			out = new FileOutputStream(file);
			write(data, out);
		} catch (Exception e) {
			logger.error("write", e);
			throw e;
		} finally {
			closeQuietly(out);
		}
	}

	public static void write(byte[] data, OutputStream out) {
		ByteArrayInputStream bis = null;
		try {
			bis = new ByteArrayInputStream(data);
			write(bis, out);
		} catch (Exception e) {
			logger.error("write", e);
		} finally {
			closeQuietly(bis);
		}
	}

	public static void write(InputStream is, String fileName) {
		File file = new File(formatPath(fileName));
		createDirs(file.getParentFile());
		write(is, file);
	}

	public static void write(InputStream is, File file) {
		FileOutputStream out = null;
		try {
			out = new FileOutputStream(file);
			write(is, out);
		} catch (Exception e) {
			logger.error("write", e);
		} finally {
			closeQuietly(out);
		}

	}

	public static void write(InputStream is, OutputStream out) {
		try {
			IOUtils.copy(is, out);
		} catch (Exception e) {
			logger.error("write", e);
		}
	}

	public static void createDirs(File path) {
		if (!path.exists()) {
			path.mkdirs();
		}
	}

	public static void delete(File path) {
		if (path.exists()) {
			path.delete();
		}
	}

	public static void move(String src, String dest) throws Exception {
		File srcFile = new File(formatPath(src)), destFile = new File(formatPath(dest));
		createDirs(destFile.getParentFile());
		delete(destFile);
		try {
			org.apache.commons.io.FileUtils.moveFile(srcFile, destFile);
		} catch (Exception e) {
			throw new Exception("文件移动错误");
		}
	}

	public static File getUniqueFile(final File file) {
		if (!file.exists()) {
			return file;
		}
		File tmpFile = new File(file.getAbsolutePath());
		File parentDir = tmpFile.getParentFile();
		int count = 1;
		String extension = FilenameUtils.getExtension(tmpFile.getName());
		String baseName = FilenameUtils.getBaseName(tmpFile.getName());
		do {
			tmpFile = new File(parentDir, baseName + "(" + count++ + ")." + extension);
		} while (tmpFile.exists());
		return tmpFile;
	}

	public static void main(String[] args) {
		// System.out.print(
		// FileUtils.readAllFile(new
		// File("D:\\ChunyuCld\\项目\\九龙坡区\\九龙坡新系统\\许可证档案\\九龙坡区生产许可资料存档-截至2015年12月9日/2015-684-九龙坡区-重庆市巴良食品有限公司-冷冻饮品（雪泥）"),
		// UUID.randomUUID().getMostSignificantBits()));
	}
}
